#include "StdAfx.h"
#include "deadZ80.h"
#include "opcodes.h"

unsigned char parity[256] = {
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
};

/*
 * execute one opcode
 *
 * reads opcode from current pc, then does its operation
 */
int CDeadZ80::Step()
{
	unsigned char tmp;
	unsigned short stmp,utmp[3];
	unsigned long ltmp;

	if(inside_irq) {
		opcode = irqfunc(user);
		inside_irq = 0;
	}
	else
		//fetch opcode from memory
		opcode = ReadMemory8(pc++);

	if(halt)
		return(0);

	//do operation of opcode
	switch(opcode) {

		case 0x00:							cycles += 4;	break;

		case 0x01:	//ld bc,imm16
			BC = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x02:	//ld (bc),a
			WriteMemory8(BC,A);
			cycles += 7;
			break;

		case 0x03:	INC16(BC);				cycles += 6;	break;
		case 0x04:	INC(B);					cycles += 4;	break;
		case 0x05:	DEC(B);					cycles += 4;	break;
		case 0x06:	B = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x07:	//rlca
			tmp = (A & 0x80) >> 7;
			A <<= 1;
			A |= tmp & 1;
			F &= ~(FLAG_N | FLAG_H | FLAG_C | 0x28);
			F |= tmp | (A & 0x28);
			break;

		case 0x08:	//ex af,af'
			utmp[0] = regs->af.word;
			regs->af.word = alt.af.word;
			alt.af.word = utmp[0];
			cycles += 4;
			break;

		case 0x09:	//add hl,bc
			ADD16(HL,BC);
			break;

			case 0x0A:	//ld a,(bc)
			A = ReadMemory8(BC);
			break;

		case 0x0B:	DEC16(BC);				cycles += 6;	break;
		case 0x0C:	INC(C);					cycles += 4;	break;
		case 0x0D:	DEC(C);					cycles += 4;	break;
		case 0x0E:	C = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x0F:	//rrca
			F = (F & (FLAG_P | FLAG_Z | FLAG_S)) | (A & 1);
			A = (A >> 1) | ((A << 7) & 0x80);
			F |= A & 0x28;
			break;

		case 0x10:	//djnz imm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if(--B > 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x11:	//ld de,imm16
			DE = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x12:	//ld (de),a
			WriteMemory8(DE,A);
			cycles += 7;
			break;

		case 0x13:	INC16(DE);				cycles += 6;	break;
		case 0x14:	INC(D);					cycles += 4;	break;
		case 0x15:	DEC(D);					cycles += 4;	break;
		case 0x16:	D = ReadMemory8(pc++);	cycles += 7;	break;
		case 0x17:	RL(A);					cycles += 4;	break;

		case 0x18:	//jr simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			pc = stmp;
			cycles += 13;
			break;

		case 0x19:	//add hl,de
			ADD16(HL,DE);
			break;

		case 0x1A:	A = ReadMemory8(DE);	cycles += 7;	break;
		case 0x1B:	DEC16(DE);				cycles += 6;	break;
		case 0x1C:	INC(E);					cycles += 4;	break;
		case 0x1D:	DEC(E);					cycles += 4;	break;
		case 0x1E:	E = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x1F:	//rra
			tmp = A & 1;
			A >>= 1;
			A |= (F << 7) & 0x80;
			F &= ~(FLAG_N | FLAG_H | FLAG_C | 0x28);
			F |= tmp | (A & 0x28);
			break;

		case 0x20:	//jr nz,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_Z) == 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x21:	//ld hl,imm16
			HL = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x22:	//ld (u16),hl
			WriteMemory16(ReadMemory16(pc),HL);
			pc += 2;
			cycles += 13;
			break;

		case 0x23:	INC16(HL);				cycles += 6;	break;
		case 0x24:	INC(H);					cycles += 4;	break;
		case 0x25:	DEC(H);					cycles += 4;	break;
		case 0x26:	H = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x27:	//daa
			DAA;
			break;

		case 0x28:	//jr z,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_Z) != 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x29:	ADD16(HL,HL);	cycles += 6;	break;

		case 0x2A:	//ld hl,(imm16)
			HL = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 10;
			break;

		case 0x2B:	DEC16(HL);		cycles += 6;	break;
		case 0x2C:	INC(L);			cycles += 4;	break;
		case 0x2D:	DEC(L);			cycles += 4;	break;
		case 0x2E:	L = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x2F:	//cpl
			A ^= 0xFF;
			F |= FLAG_N | FLAG_H | 0x28;
			break;

		case 0x30:	//jr nc,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_C) == 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x31:	//ld sp,nnnn
			sp = ReadMemory16(pc);
			pc += 2;
			cycles += 20;
			break;

		case 0x32:	//ld (u16),a
			WriteMemory8(ReadMemory16(pc),A);
			pc += 2;
			cycles += 13;
			break;

		case 0x33:	INC16(sp);		cycles += 7;		break;

		case 0x34:	//inc (hl)
			tmp = ReadMemory8(HL);
			stmp = tmp + 1;
			WriteMemory8(HL,(u8)stmp);
			F &= ~(FLAG_S | FLAG_Z | FLAG_V | FLAG_N | FLAG_H | 0x28);
			F |= stmp & 0x28;
			checkSZ(stmp & 0xFF);
			checkV(tmp,1,stmp);
			if((tmp & 8) && (1 & 8))
				F |= FLAG_H;
			cycles += 4;
			break;

		case 0x35:	//dec (hl)
			tmp = ReadMemory8(HL);
			DEC(tmp);
			WriteMemory8(HL,tmp);
			cycles += 7;
			break;

		case 0x36:	//ld (hl),n
			WriteMemory8(HL,ReadMemory8(pc++));
			cycles += 7;
			break;

		case 0x37:
			F |= FLAG_C;
			break;

		case 0x38:	//jr c,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_C) != 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x39:	//add hl,sp
			ADD16(HL,sp);
			cycles += 7;
			break;

		case 0x3A:	//ld a,(nn)
			A = ReadMemory8(ReadMemory16(pc));
			pc += 2;
			cycles += 10;
			break;

		case 0x3B:	DEC16(sp);							cycles += 6;	break;
		case 0x3C:	INC(A);								cycles += 4;	break;
		case 0x3D:	DEC(A);								cycles += 4;	break;
		case 0x3E:	A = ReadMemory8(pc++);				cycles += 7;	break;

		case 0x3F:	//ccf
			F &= FLAG_P | FLAG_Z | FLAG_S;
			F |= (F & FLAG_C) ? FLAG_H : FLAG_C;
			F |= A & 0x28;
			break;

		case 0x40:	B = B;								cycles += 4;	break;
		case 0x41:	B = C;								cycles += 4;	break;
		case 0x42:	B = D;								cycles += 4;	break;
		case 0x43:	B = E;								cycles += 4;	break;
		case 0x44:	B = H;								cycles += 4;	break;
		case 0x45:	B = L;								cycles += 4;	break;
		case 0x46:	B = ReadMemory8(HL);				cycles += 7;	break;
		case 0x47:	B = A;								cycles += 4;	break;
		case 0x48:	C = B;								cycles += 4;	break;
		case 0x49:	C = C;								cycles += 4;	break;
		case 0x4A:	C = D;								cycles += 4;	break;
		case 0x4B:	C = E;								cycles += 4;	break;
		case 0x4C:	C = H;								cycles += 4;	break;
		case 0x4D:	C = L;								cycles += 4;	break;
		case 0x4E:	C = ReadMemory8(HL);				cycles += 7;	break;
		case 0x4F:	C = A;								cycles += 4;	break;
		case 0x50:	D = B;								cycles += 4;	break;
		case 0x51:	D = C;								cycles += 4;	break;
		case 0x52:	D = D;								cycles += 4;	break;
		case 0x53:	D = E;								cycles += 4;	break;
		case 0x54:	D = H;								cycles += 4;	break;
		case 0x55:	D = L;								cycles += 4;	break;
		case 0x56:	D = ReadMemory8(HL);				cycles += 7;	break;
		case 0x57:	D = A;								cycles += 4;	break;
		case 0x58:	E = B;								cycles += 4;	break;
		case 0x59:	E = C;								cycles += 4;	break;
		case 0x5A:	E = D;								cycles += 4;	break;
		case 0x5B:	E = E;								cycles += 4;	break;
		case 0x5C:	E = H;								cycles += 4;	break;
		case 0x5D:	E = L;								cycles += 4;	break;
		case 0x5E:	E = ReadMemory8(HL);				cycles += 7;	break;
		case 0x5F:	E = A;								cycles += 4;	break;
		case 0x60:	H = B;								cycles += 4;	break;
		case 0x61:	H = C;								cycles += 4;	break;
		case 0x62:	H = D;								cycles += 4;	break;
		case 0x63:	H = E;								cycles += 4;	break;
		case 0x64:	H = H;								cycles += 4;	break;
		case 0x65:	H = L;								cycles += 4;	break;
		case 0x66:	H = ReadMemory8(HL);				cycles += 7;	break;
		case 0x67:	H = A;								cycles += 4;	break;
		case 0x68:	L = B;								cycles += 4;	break;
		case 0x69:	L = C;								cycles += 4;	break;
		case 0x6A:	L = D;								cycles += 4;	break;
		case 0x6B:	L = E;								cycles += 4;	break;
		case 0x6C:	L = H;								cycles += 4;	break;
		case 0x6D:	L = L;								cycles += 4;	break;
		case 0x6E:	L = ReadMemory8(HL);				cycles += 7;	break;
		case 0x6F:	L = A;								cycles += 4;	break;
		case 0x70:	WriteMemory8(HL,B);					cycles += 7;	break;
		case 0x71:	WriteMemory8(HL,C);					cycles += 7;	break;
		case 0x72:	WriteMemory8(HL,D);					cycles += 7;	break;
		case 0x73:	WriteMemory8(HL,E);					cycles += 7;	break;
		case 0x74:	WriteMemory8(HL,H);					cycles += 7;	break;
		case 0x75:	WriteMemory8(HL,L);					cycles += 7;	break;
		case 0x76:	halt = 1;	pc--;					cycles += 2;	break;
		case 0x77:	WriteMemory8(HL,A);					cycles += 7;	break;
		case 0x78:	A = B;								cycles += 4;	break;
		case 0x79:	A = C;								cycles += 4;	break;
		case 0x7A:	A = D;								cycles += 4;	break;
		case 0x7B:	A = E;								cycles += 4;	break;
		case 0x7C:	A = H;								cycles += 4;	break;
		case 0x7D:	A = L;								cycles += 4;	break;
		case 0x7E:	A = ReadMemory8(HL);				cycles += 7;	break;
		case 0x7F:	A = A;								cycles += 4;	break;
		case 0x80:	ADD(B);								cycles += 4;	break;
		case 0x81:	ADD(C);								cycles += 4;	break;
		case 0x82:	ADD(D);								cycles += 4;	break;
		case 0x83:	ADD(E);								cycles += 4;	break;
		case 0x84:	ADD(H);								cycles += 4;	break;
		case 0x85:	ADD(L);								cycles += 4;	break;
		case 0x86:	tmp = ReadMemory8(HL); ADD(tmp);	cycles += 7;	break;
		case 0x87:	ADD(A);								cycles += 4;	break;
		case 0x88:	ADC(B);								cycles += 4;	break;
		case 0x89:	ADC(C);								cycles += 4;	break;
		case 0x8A:	ADC(D);								cycles += 4;	break;
		case 0x8B:	ADC(E);								cycles += 4;	break;
		case 0x8C:	ADC(H);								cycles += 4;	break;
		case 0x8D:	ADC(L);								cycles += 4;	break;
		case 0x8E:	tmp = ReadMemory8(HL); ADC(tmp);	cycles += 7;	break;
		case 0x8F:	ADC(A);								cycles += 4;	break;
		case 0x90:	SUB(B);								cycles += 4;	break;
		case 0x91:	SUB(C);								cycles += 4;	break;
		case 0x92:	SUB(D);								cycles += 4;	break;
		case 0x93:	SUB(E);								cycles += 4;	break;
		case 0x94:	SUB(H);								cycles += 4;	break;
		case 0x95:	SUB(L);								cycles += 4;	break;
		case 0x96:	tmp = ReadMemory8(HL); SUB(tmp);	cycles += 7;	break;
		case 0x97:	SUB(A);								cycles += 4;	break;
		case 0x98:	SBC(B);								cycles += 4;	break;
		case 0x99:	SBC(C);								cycles += 4;	break;
		case 0x9A:	SBC(D);								cycles += 4;	break;
		case 0x9B:	SBC(E);								cycles += 4;	break;
		case 0x9C:	SBC(H);								cycles += 4;	break;
		case 0x9D:	SBC(L);								cycles += 4;	break;
		case 0x9E:	tmp = ReadMemory8(HL); SBC(tmp);	cycles += 7;	break;
		case 0x9F:	SBC(A);								cycles += 4;	break;
		case 0xA0:	AND(B);								cycles += 4;	break;
		case 0xA1:	AND(C);								cycles += 4;	break;
		case 0xA2:	AND(D);								cycles += 4;	break;
		case 0xA3:	AND(E);								cycles += 4;	break;
		case 0xA4:	AND(H);								cycles += 4;	break;
		case 0xA5:	AND(L);								cycles += 4;	break;
		case 0xA6:	tmp = ReadMemory8(HL); AND(tmp);	cycles += 7;	break;
		case 0xA7:	AND(A);								cycles += 4;	break;
		case 0xA8:	XOR(B);								cycles += 4;	break;
		case 0xA9:	XOR(C);								cycles += 4;	break;
		case 0xAA:	XOR(D);								cycles += 4;	break;
		case 0xAB:	XOR(E);								cycles += 4;	break;
		case 0xAC:	XOR(H);								cycles += 4;	break;
		case 0xAD:	XOR(L);								cycles += 4;	break;
		case 0xAE:	tmp = ReadMemory8(HL); XOR(tmp);			cycles += 7;	break;
		case 0xAF:	XOR(A);										cycles += 4;	break;
		case 0xB0:	OR(B);										cycles += 4;	break;
		case 0xB1:	OR(C);										cycles += 4;	break;
		case 0xB2:	OR(D);										cycles += 4;	break;
		case 0xB3:	OR(E);										cycles += 4;	break;
		case 0xB4:	OR(H);										cycles += 4;	break;
		case 0xB5:	OR(L);										cycles += 4;	break;
		case 0xB6:	tmp = ReadMemory8(HL); OR(tmp);			cycles += 7;	break;
		case 0xB7:	OR(A);										cycles += 4;	break;
		case 0xB8:	CP(B);										cycles += 4;	break;
		case 0xB9:	CP(C);										cycles += 4;	break;
		case 0xBA:	CP(D);										cycles += 4;	break;
		case 0xBB:	CP(E);										cycles += 4;	break;
		case 0xBC:	CP(H);										cycles += 4;	break;
		case 0xBD:	CP(L);										cycles += 4;	break;
		case 0xBE:	tmp = ReadMemory8(HL); CP(tmp);			cycles += 7;	break;
		case 0xBF:	CP(A);										cycles += 4;	break;
		case 0xC0:	RET((F & FLAG_Z) == 0);											break;
		case 0xC1:	POP16(BC);									cycles += 10;	break;
		case 0xC2:	JR((F & FLAG_Z) == 0);											break;
		case 0xC3:	JP(ReadMemory16(pc));				cycles += 0;	break;
		case 0xC4:	CALL((F & FLAG_Z) == 0);										break;
		case 0xC5:	PUSH16(BC);									cycles += 11;	break;
		case 0xC6:	tmp = ReadMemory8(pc++);ADD(tmp);	cycles += 4;	break;
		case 0xC7:	RST(0x00);														break;
		case 0xC8:	RET((F & FLAG_Z) != 0);											break;
		case 0xC9:	RET(1);															break;
		case 0xCA:	JR((F & FLAG_Z) != 0);											break;
		case 0xCB:	return(ExecuteOpcodeCB());
		case 0xCC:	CALL((F & FLAG_Z) != 0);										break;
		case 0xCD:	CALL(1);														break;
		case 0xCE:	tmp = ReadMemory8(pc++); ADC(tmp);	cycles += 7;	break;
		case 0xCF:	RST(0x08);														break;
		case 0xD0:	RET((F & FLAG_C) == 0);											break;
		case 0xD1:	POP16(DE);									cycles += 10;	break;
		case 0xD2:	JR((F & FLAG_C) == 0);											break;
		case 0xD3:	tmp = ReadMemory8(pc++); OP_OUT(tmp,A,A);		cycles += 11;		break;
		case 0xD4:	CALL((F & FLAG_C) == 0);										break;
		case 0xD5:	PUSH16(DE);									cycles += 11;	break;
		case 0xD6:	SUB(ReadMemory8(pc++));				cycles += 14;	break;
		case 0xD7:	RST(0x10);														break;
		case 0xD8:	RET((F & FLAG_C) != 0);											break;
		case 0xD9:	EXX();															break;
		case 0xDA:	JR((F & FLAG_C) != 0);											break;

		case 0xDC:	CALL((F & FLAG_C) != 0);										break;
		case 0xDD:	return(ExecuteOpcodeDD());
		case 0xDE:	SBC(ReadMemory8(pc++));								cycles += 4;	break;
		case 0xDF:	RST(0x18);														break;
		case 0xE0:	RET((F & FLAG_P) == 0);											break;
		case 0xE1:	POP16(HL);									cycles += 10;	break;
		case 0xE2:	JR((F & FLAG_P) == 0);											break;

		case 0xE4:	CALL((F & FLAG_P) == 0);										break;
		case 0xE5:	PUSH16(HL);									cycles += 11;	break;
		case 0xE6:	AND(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xE7:	RST(0x20);														break;
		case 0xE8:	RET((F & FLAG_P) != 0);											break;
		case 0xE9:	JP(HL);															break;
		case 0xEA:	JR((F & FLAG_P) != 0);											break;
		case 0xEB:	EX(DE,HL);														break;
		case 0xEC:	CALL((F & FLAG_P) != 0);										break;
		case 0xED:	return(ExecuteOpcodeED());
		case 0xEE:	XOR(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xEF:	RST(0x28);														break;
		case 0xF0:	RET((F & FLAG_S) == 0);											break;
		case 0xF1:	POP16(AF);									cycles += 10;	break;
		case 0xF2:	JR((F & FLAG_S) == 0);											break;
		case 0xF3:	iff1 = iff2 = 0;					cycles += 4;	break;
		case 0xF4:	CALL((F & FLAG_S) == 0);										break;
		case 0xF5:	PUSH16(AF);														break;
		case 0xF6:	OR(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xF7:	RST(0x30);														break;
		case 0xF8:	RET((F & FLAG_S) != 0);											break;
		case 0xF9:	sp = HL;													break;
		case 0xFA:	JR((F & FLAG_S) != 0);											break;
		case 0xFB:	iff1 = iff2 = 1;					cycles += 4;	break;
		case 0xFC:	CALL((F & FLAG_S) != 0);										break;
		case 0xFD:	return(ExecuteOpcodeFD());
		case 0xFE:	tmp = ReadMemory8(pc++);CP(tmp);	cycles += 7;	break;
		case 0xFF:	RST(0x38);														break;

		default:	//bad opcode
			message("bad opcode = $%02X\n",opcode);
			return(1);

	}
	return(0);
}




















